#include <cstdio>
#include <systemc>

using namespace sc_core;
using namespace sc_dt;
using namespace std;

SC_MODULE(Wire) {
    sc_in<bool>  in;
    sc_out<bool> out;

    void process() {
        out.write(in.read());
        printf("@%s %s: in=%d, out=%d\n", sc_time_stamp().to_string().c_str(), this->name(), in.read(), out.read());
    }

    SC_CTOR(Wire) {
        SC_METHOD(process);
        sensitive << in;

        dont_initialize();
    }

    void before_end_of_elaboration() {
        printf("%s::before_end_of_elaboration()\n", this->name());
    }
    void end_of_elaboration() {
        printf("%s::end_of_elaboration()\n", this->name());
    }
    void start_of_simulation() {
        printf("%s::start_of_simulation()\n", this->name());
    }
    void end_of_simulation() {
        printf("%s::end_of_simulation()\n", this->name());
    }
};

SC_MODULE(Top) {
    sc_in<bool>  in;
    sc_out<bool> out;

    Wire wire1;
    Wire wire2;

    sc_signal<bool> mid;

    SC_CTOR(Top): wire1("wire1"), wire2("wire2") {
        wire1.in(in);
        wire1.out(mid);
        wire2.in(mid);
        wire2.out(out);

        SC_METHOD(monitor);
        sensitive << in << mid << out;

        dont_initialize();
    }

    void monitor() {
        printf("@%s %s: in=%d, mid=%d, out=%d\n", sc_time_stamp().to_string().c_str(), this->name(), in.read(), mid.read(), out.read());
    }

    void before_end_of_elaboration() {
        printf("%s::before_end_of_elaboration()\n", this->name());
    }
    void end_of_elaboration() {
        printf("%s::end_of_elaboration()\n", this->name());
    }
    void start_of_simulation() {
        printf("%s::start_of_simulation()\n", this->name());
    }
    void end_of_simulation() {
        printf("%s::end_of_simulation()\n", this->name());
    }
};

int sc_main(int argc, char **argv) {
    // 信号连接关系: sig_in -> wire1.in -> wire1.out -> top.mid -> wire2.in -> wire2.out -> sig_out
    sc_signal<bool> sig_in, sig_out;
    Top top("top");
    top.in(sig_in);
    top.out(sig_out);

    sig_in.write(true);
    sc_start(2, SC_NS);
    printf("sig_in=%d, sig_out=%d\n", sig_in.read(), sig_out.read());
    sig_in.write(false);
    sc_start(2, SC_NS);
    printf("sig_in=%d, sig_out=%d\n", sig_in.read(), sig_out.read());

    sig_in.write(true);
    sc_start(2, SC_NS);
    printf("sig_in=%d, sig_out=%d\n", sig_in.read(), sig_out.read());

    return 0;
}

/* Output:
@0 s top.wire1: in=1, out=0
@0 s top: in=1, mid=0, out=0
@0 s top.wire2: in=1, out=0
@0 s top: in=1, mid=1, out=0
@0 s top: in=1, mid=1, out=1
sig_in=1, sig_out=1
@2 ns top.wire1: in=0, out=1
@2 ns top: in=0, mid=1, out=1
@2 ns top.wire2: in=0, out=1
@2 ns top: in=0, mid=0, out=1
@2 ns top: in=0, mid=0, out=0
sig_in=0, sig_out=0
@4 ns top.wire1: in=1, out=0
@4 ns top: in=1, mid=0, out=0
@4 ns top.wire2: in=1, out=0
@4 ns top: in=1, mid=1, out=0
@4 ns top: in=1, mid=1, out=1
sig_in=1, sig_out=1
*/

/* Analysis:
[Initialization]: 处理 sig_in 更新请求, sig_in(即wire.in) 值 0->1, 触发 wire1.process;
[Delta Cycle 1 - Evaluate]: wire1.process 执行, 请求更新 wire1.out(即 top.mid);
    @0 s top.wire1: in=1, out=0
    @0 s top: in=1, mid=0, out=0
[Delta Cycle 1 - Update]: 更新 wire1.out(即top.mid) 值 0->1;
[Delta Cycle 1 - Delta Notification]: wire1.out(即top.mid)的值发生变化, 触发 wire2.process 和 top.monitor;


[Delta Cycle 2 - Evaluate]: wire2.process 执行, 请求更新 wire2.out(即top.out/sig_out); top.monitor 执行;
    @0 s top.wire2: in=1, out=0
    @0 s top: in=1, mid=1, out=0
[Delta Cycle 2 - Update]: 更新 wire2.out(即top.out/sig_out) 值 0->1;
[Delta Cycle 2 - Delta Notification]: wire2.out(即top.out/sig_out)的值发生变化, 触发 top.monitor;

[Delta Cycle 3 - Evaluate]: top.monitor 执行;
    @0 s top: in=1, mid=1, out=1
[Delta Cycle 3 - Update]: 无更新;
[Delta Cycle 3 - Delta Notification]: 无触发;

在 0 s 时刻系统达到稳定, 没有更多可运行的进程. 调度器推进时间到下一个事件的时刻, 即 sc_start 指定的 2 ns.
*/
